home *** CD-ROM | disk | FTP | other *** search
/ One Click 14 / OneClick14.iso / Ferramentas / Convert XLS to Pdf / xls2pdf_setup.exe / {app} / lib / gs_ttf.ps < prev    next >
Encoding:
Text File  |  2002-10-04  |  33.0 KB  |  1,104 lines

  1. %    Copyright (C) 1996, 2000 Aladdin Enterprises.  All rights reserved.
  2. % This software is provided AS-IS with no warranty, either express or
  3. % implied.
  4. % This software is distributed under license and may not be copied,
  5. % modified or distributed except as expressly authorized under the terms
  6. % of the license contained in the file LICENSE in this distribution.
  7. % For more information about licensing, please refer to
  8. % http://www.ghostscript.com/licensing/. For information on
  9. % commercial licensing, go to http://www.artifex.com/licensing/ or
  10. % contact Artifex Software, Inc., 101 Lucas Valley Road #110,
  11. % San Rafael, CA  94903, U.S.A., +1(415)492-9861.
  12.  
  13. % $Id: gs_ttf.ps,v 1.21 2002/10/03 19:40:27 igor Exp $
  14. % Support code for direct use of TrueType fonts.
  15. % (Not needed for Type 42 fonts.)
  16.  
  17. % Note that if you want to use this file without including the ttfont.dev
  18. % option when you built Ghostscript, you will need to load the following
  19. % files before this one:
  20. %    lib/gs_mgl_e.ps
  21. %    lib/gs_mro_e.ps
  22. %    lib/gs_wan_e.ps
  23.  
  24. % Thanks to B. Jackowski and GUST (the Polish TeX Users' Group) for
  25. % the glyf-splitting code.
  26.  
  27. % ---------------- Font loading machinery ---------------- %
  28.  
  29. % Augment the FONTPATH machinery so it recognizes TrueType fonts.
  30.  
  31. /.scanfontheaders where {
  32.   pop /.scanfontheaders [
  33.    .scanfontheaders aload pop (\000\001\000\000*) (true*)
  34.   ] def
  35. } if
  36.  
  37. % <file> <key> .findfontvalue <value> true
  38. % <file> <key> .findfontvalue false
  39. % Closes the file in either case.
  40. /.findnonttfontvalue /.findfontvalue load def
  41. /.findfontvalue {
  42.   1 index read pop 2 index 1 index unread
  43.   dup 0 eq exch (t) 0 get eq or {
  44.         % If this is a font at all, it's a TrueType font.
  45.     dup /FontType eq {
  46.       pop closefile 42 true
  47.     } {
  48.       dup /FontName eq { pop .findttfontname } { pop closefile false } ifelse
  49.     } ifelse
  50.   } {
  51.         % Not a TrueType font.
  52.     .findnonttfontvalue
  53.   } ifelse
  54. } bind def
  55.  
  56. % <file> .findttfontname <fname> true
  57. % <file> .findttfontname false
  58. % Closes the file in either case.
  59. /.findttfontname {
  60.   .loadttfonttables
  61.   tabdict /name .knownget {
  62.     dup 8 getu32 f exch setfileposition
  63.     12 getu32 string f exch readstring pop
  64.     6 findname
  65.   } {
  66.     false
  67.   } ifelse
  68.   f closefile end end
  69. } bind def
  70.  
  71. % Load a font file that might be a TrueType font.
  72.  
  73. % <file> .loadfontfile -
  74. /.loadnonttfontfile /.loadfontfile load def
  75. /.loadfontfile {
  76.   dup read pop 2 copy unread 0 eq {
  77.         % If this is a font at all, it's a TrueType font.
  78.     .loadttfont pop
  79.   } {
  80.         % Not a TrueType font.
  81.     .loadnonttfontfile
  82.   } ifelse
  83. } bind def
  84.  
  85. % ---------------- Automatic Type 42 generation ---------------- %
  86.  
  87. % Load a TrueType font from a file as a Type 42 PostScript font.
  88. % The thing that makes this really messy is the handling of encodings.
  89. % There are 2 interacting tables that affect the encoding:
  90. %       'cmap' provides multiple maps from character codes to glyph indices
  91. %       'post' maps glyph indices to glyph names (if present)
  92. % What we need to get out of this is:
  93. %       Encoding mapping character codes to glyph names
  94. %         (the composition of cmap and post)
  95. %       CharStrings mapping glyph names to glyph indices
  96. %         (the inverse of post)
  97. % If the post table is missing, we have to take a guess based on the cmap
  98. % table.
  99.  
  100. /.loadttfontdict 50 dict dup begin
  101.  
  102. /orgXUID AladdinEnterprisesXUID def
  103. /maxstring 32000 def    % half the maximum length of a PostScript string,
  104.             % must be a multiple of 4 (for hmtx / loca / vmtx)
  105.  
  106. % Define the Macintosh standard mapping from characters to glyph indices.
  107. /MacRomanEncoding dup .findencoding def
  108. /MacGlyphEncoding dup .findencoding def
  109.  
  110. % Invert the MacRomanEncoding.
  111. /.romanmacdict 300 dict
  112. 0 1 MacRomanEncoding length 1 sub {
  113.   MacRomanEncoding 1 index get
  114.         % Stack: dict index charname
  115.   dup /.notdef ne {
  116.     exch 2 index 2 index .knownget {
  117.       dup type /arraytype eq {
  118.     [ exch aload pop counttomark 2 add -1 roll ]
  119.       } {
  120.     exch 2 array astore
  121.       } ifelse
  122.     } if 2 index 3 1 roll put
  123.   } {
  124.     pop pop
  125.   } ifelse
  126. } for def
  127.  
  128. % Define remapping for misnamed glyphs in TrueType 'post' tables.
  129. % There are probably a lot more than this!
  130. /postremap mark
  131.   /Cdot /Cdotaccent
  132.   /Edot /Edotaccent
  133.   /Eoverdot /Edotaccent
  134.   /Gdot /Gdotaccent
  135.   /Ldot /Ldotaccent
  136.   /Zdot /Zdotaccent
  137.   /cdot /cdotaccent 
  138.   /edot /edotaccent 
  139.   /eoverdot /edotaccent
  140.   /gdot /gdotaccent 
  141.   /ldot /ldotaccent
  142.   /zdot /zdotaccent 
  143. .dicttomark readonly def
  144.  
  145. % ---- Utilities ---- %
  146.  
  147. % Define a serial number for creating unique XUIDs for TrueType fonts.
  148. % We used to use the checkSumAdjustment value from the font, but this is
  149. % not reliable, since some fonts don't set it correctly.
  150. % Note that we must do this in a string to make it immune to save/restore.
  151. /xuidstring <80000000> def
  152. /curxuid {        % - curxuid <int>
  153.   0 xuidstring { exch 8 bitshift exch add } forall
  154. } bind def
  155. /nextxuid {        % - nextxuid -
  156.   3 -1 0 {
  157.     xuidstring 1 index 2 copy get dup 255 ne {
  158.       1 add put pop exit
  159.     } if pop 0 put pop
  160.   } for
  161. } bind def
  162.  
  163. % <string> <index> getu16 <integer>
  164. /getu16 {
  165.   2 copy get 8 bitshift 3 1 roll 1 add get add
  166. } bind def
  167.  
  168. % <string> <index> gets16 <integer>
  169. /gets16 {
  170.   getu16 16#8000 xor 16#8000 sub
  171. } bind def
  172.  
  173. % <string> <index> getu32 <integer>
  174. /getu32 {
  175.   2 copy getu16 16 bitshift 3 1 roll 2 add getu16 add
  176. } bind def
  177.  
  178. % <string> <index> gets32 <integer>
  179. /gets32 {
  180.   2 copy gets16 16 bitshift 3 1 roll 2 add getu16 add
  181. } bind def
  182.  
  183. % <string> <index> <integer> putu16 -
  184. /putu16 {
  185.   3 copy -8 bitshift put
  186.   exch 1 add exch 16#ff and put
  187. } bind def
  188.  
  189. % <string> <index> <integer> putu32 -
  190. /putu32 {
  191.   3 copy -16 bitshift putu16
  192.   exch 2 add exch 16#ffff and putu16
  193. } bind def
  194.  
  195. % <nametable> <nameid> findname <string> true
  196. % <nametable> <nameid> findname false
  197. /findname {
  198.   DEBUG { (findname: ) print dup =only  } if
  199.   false 3 1 roll 0 1 3 index 2 getu16 1 sub {
  200.         % Stack: false table id index
  201.     12 mul 6 add 2 index exch 12 getinterval
  202.     dup 6 getu16 2 index eq {
  203.         % We found the name we want.
  204.       exch pop
  205.         % Stack: false table record
  206.       dup 10 getu16 2 index 4 getu16 add
  207.       1 index 8 getu16 4 -1 roll 3 1 roll getinterval exch
  208.         % Stack: false string record
  209.         % Check for 8- vs. 16-bit characters.
  210.       is2byte { string2to1 } if true null 4 -1 roll exit
  211.     } if pop
  212.   } for pop pop
  213.   DEBUG {
  214.     dup { ( = ) print 1 index == } { ( not found) = } ifelse
  215.   } if
  216. } bind def
  217.  
  218. % <namerecord> is2byte <bool>
  219. /is2byte {
  220.   dup 0 getu16 {
  221.     { pop true }        % Apple Unicode
  222.     { pop false }        % Macintosh Script manager
  223.     { 1 getu16 1 eq }        % ISO
  224.     { 1 getu16 1 eq }        % Microsoft
  225.   } exch get exec
  226. } bind def
  227.  
  228. % <string2> string2to1 <string>
  229. /string2to1 {
  230.   dup length 2 idiv string dup
  231.   0 1 3 index length 1 sub {
  232.     3 index 1 index 2 mul 1 add get put dup
  233.   } for pop exch pop
  234. } bind def
  235.  
  236. % Each procedure in this dictionary is called as follows:
  237. %       <encodingtable> proc <glypharray>
  238. /cmapformats mark
  239.   0 {        % Apple standard 1-to-1 mapping.
  240.     6 256 getinterval { } forall 256 packedarray
  241.   } bind
  242.   2 {        % Apple 16bit CJK (ShiftJIS etc)
  243.  
  244.     % /sHK_sz        subHeaderKey_size    % 1 * uint16
  245.     % /sH_sz        subHeader_size        % 4 * uint16
  246.     % /sH_len        subHeader_length
  247.     % /cmapf2_tblen    total table length
  248.     % /cmapf2_lang    language code (not used)
  249.     % /sHKs        subHeaderKeys
  250.  
  251.     /sHK_sz 2 def
  252.     /sH_sz 8 def
  253.     dup 2 getu16 /cmapf2_tblen exch def
  254.  
  255.     dup 4 getu16 /cmapf2_lang exch def
  256.  
  257.     dup 6 256 sHK_sz mul getinterval /sHKs exch def
  258.  
  259.     0        % initialization value for /sH_len
  260.     0 1 255 {
  261.        sHKs exch
  262.        2 mul getu16
  263.        1 index    % get current max
  264.        1 index    % get current subHeaderKey
  265.        lt {exch} if pop
  266.     } for
  267.     /sH_len exch def
  268.  
  269.     dup 6 256 sHK_sz mul add
  270.     cmapf2_tblen 1 index sub getinterval
  271.     /sH_gIA exch def
  272.  
  273.     /cmapf2_glyph_array 65535 array def
  274.  
  275.     /.cmapf2_putGID {
  276.         /cmapf2_ch cmapf2_ch_hi 8 bitshift cmapf2_ch_lo add def
  277.         firstCode cmapf2_ch_lo le
  278.         cmapf2_ch_lo firstCode entryCount add lt
  279.         and { % true: j is inside
  280.             sH_offset idRangeOffset add        % offset to gI
  281.             cmapf2_ch_lo firstCode sub 2 mul    % rel. pos. in range
  282.             add 6 add                % offset in sH_gIA
  283.             sH_gIA exch getu16
  284.             dup 0 gt { %
  285.                 idDelta add
  286.                 cmapf2_glyph_array exch cmapf2_ch exch put
  287.             } {
  288.                 pop
  289.                 % cmapf2_glyph_array cmapf2_ch 0 put
  290.             } ifelse
  291.         } {   % false: j is outside
  292.             % cmapf2_glyph_array cmapf2_ch 0 put
  293.         } ifelse
  294.     } def
  295.  
  296.     16#00 1 16#ff { % hi_byte scan
  297.         /cmapf2_ch_hi exch def
  298.         sHKs cmapf2_ch_hi sHK_sz mul getu16
  299.         /sH_offset exch def
  300.         sH_gIA sH_offset sH_sz getinterval
  301.             dup 0 getu16 /firstCode exch def
  302.             dup 2 getu16 /entryCount exch def
  303.             dup 4 gets16 /idDelta exch def
  304.             dup 6 getu16 /idRangeOffset exch def
  305.         pop
  306.         sH_offset 0 eq {
  307.            /cmapf2_ch_lo cmapf2_ch_hi def
  308.            /cmapf2_ch_hi 0 def
  309.            .cmapf2_putGID
  310.         } {
  311.            16#00 1 16#ff { % lo_byte scan
  312.                /cmapf2_ch_lo exch def
  313.                .cmapf2_putGID
  314.            } for
  315.         } ifelse
  316.      } for
  317.      pop
  318.      0 1 cmapf2_glyph_array length 1 sub { % rewrite null -> 0.
  319.         dup cmapf2_glyph_array exch get
  320.         null eq { cmapf2_glyph_array exch 0 put } {pop} ifelse
  321.      } for
  322.      cmapf2_glyph_array
  323.   } bind
  324.   4 {        % Microsoft/Adobe segmented mapping.
  325.     /etab exch def
  326.     /nseg2 etab 6 getu16 def
  327.     14 /endc etab 2 index nseg2 getinterval def
  328.         % The Apple TrueType documentation omits the 2-byte
  329.         % 'reserved pad' that follows the endCount vector!
  330.     2 add
  331.     nseg2 add /startc etab 2 index nseg2 getinterval def
  332.     nseg2 add /iddelta etab 2 index nseg2 getinterval def
  333.     nseg2 add /idroff etab 2 index nseg2 getinterval def
  334.         % The following hack allows us to properly handle
  335.         % idiosyncratic fonts that start at 0xf000:
  336.     pop
  337.     /firstcode startc 0 getu16 16#ff00 and dup 16#f000 ne { pop 0 } if def
  338.     /putglyph {
  339.       glyphs code 3 -1 roll put /code code 1 add def
  340.     } bind def
  341.         % Do a first pass to compute the size of the glyphs array.
  342.     /numcodes 0 def /glyphs 0 0 2 nseg2 3 sub {
  343.         % Stack: /glyphs numglyphs i2
  344.       /i2 exch def
  345.       /scode startc i2 getu16 def
  346.       /ecode endc i2 getu16 def
  347.       numcodes scode firstcode sub
  348.         % Hack for fonts that have only 0x0000 and 0xf000 ranges
  349.       %dup 16#e000 ge { 255 and } if
  350.       % the previous line is obstructive to CJK fonts, so it was removed
  351.       exch sub 0 .max ecode scode sub 1 add add
  352.       exch 1 index add exch
  353.       numcodes add /numcodes exch def
  354.     } for array def
  355.         % Now fill in the array.
  356.     /numcodes 0 def /code 0 def
  357.     0 2 nseg2 3 sub {
  358.       /i2 exch def
  359.       /scode startc i2 getu16 def
  360.       /ecode endc i2 getu16 def
  361.       numcodes scode firstcode sub
  362.         % Hack for fonts that have only 0x0000 and 0xf000 ranges
  363.       %dup 16#e000 ge { 255 and } if
  364.       % the previous line is obstructive to CJK fonts, so it was removed
  365.       exch sub 0 .max dup { 0 putglyph } repeat
  366.       ecode scode sub 1 add add numcodes add /numcodes exch def
  367.       /delta iddelta i2 gets16 def
  368.       DEBUG {
  369.     (scode=) print scode =only
  370.     ( ecode=) print ecode =only
  371.     ( delta=) print delta =only
  372.     ( droff=) print idroff i2 getu16 =
  373.       } if
  374.       idroff i2 getu16 dup 0 eq {
  375.     pop scode delta add 65535 and 1 ecode delta add 65535 and
  376.     { putglyph } for
  377.       } {    % The +2 is for the 'reserved pad'.
  378.         /gloff exch 14 nseg2 3 mul add 2 add i2 add add def
  379.         0 1 ecode scode sub {
  380.       2 mul gloff add etab exch getu16
  381.       dup 0 ne { delta add 65535 and } if putglyph
  382.     } for
  383.       } ifelse
  384.     } for glyphs /glyphs null def    % for GC
  385.   } bind
  386.   6 {        % Single interval lookup.
  387.     dup 6 getu16 /firstcode exch def dup 8 getu16 /ng exch def
  388.     firstcode ng add array
  389.         % Stack: tab array
  390.         % Fill elements 0 .. firstcode-1 with 0
  391.     0 1 firstcode 1 sub { 2 copy 0 put pop } for
  392.     dup firstcode ng getinterval
  393.         % Stack: tab array subarray
  394.         % Fill elements firstcode .. firstcode+nvalue-1 with glyph values
  395.     0 1 ng 1 sub {
  396.       dup 2 mul 10 add 4 index exch getu16 3 copy put pop pop
  397.     } for pop exch pop
  398.   } bind
  399. .dicttomark readonly def                % cmapformats
  400.  
  401. % <cmaptab> cmaparray <glypharray>
  402. /cmaparray {
  403.   dup 0 getu16 cmapformats exch .knownget {
  404.     DEBUG {
  405.       (cmap: format ) print 1 index 0 getu16 = flush
  406.     } if exec
  407.   } {
  408.     (Can't handle format ) print 0 getu16 = flush
  409.     0 1 255 { } for 256 packedarray
  410.   } ifelse
  411.   DEBUG {
  412.     (cmap: length=) print dup length = dup ==
  413.   } if
  414. } bind def
  415.  
  416. % Each procedure in this dictionary is called as follows:
  417. %       posttable <<proc>> glyphencoding
  418. /postformats mark
  419.   16#00010000  {    % 258 standard Macintosh glyphs.
  420.     pop MacGlyphEncoding
  421.   }
  422.   16#00020000  {    % Detailed map, required by Microsoft fonts.
  423.     dup length 36 lt {
  424.       DEBUG { (post format 2.0 invalid.) = flush } if
  425.       pop [ ]
  426.     } {
  427.     /postglyphs exch def
  428.       postglyphs 32 getu16 /numglyphs exch def
  429.       /glyphnames numglyphs 2 mul 34 add def
  430.       [ 0 1 numglyphs 1 sub {
  431.     2 mul 34 add postglyphs exch getu16
  432.     dup 258 lt {
  433.       MacGlyphEncoding exch get
  434.     } {
  435.       dup 32768 ge {
  436.         % According to the published TrueType spec, such values are
  437.         % "reserved for future use", but at least some PDF files
  438.         % produced by the Adobe PDF library contain entries with a
  439.         % value of 16#ffff.
  440.         pop /.notdef
  441.       } {
  442.         258 sub glyphnames exch {
  443.           postglyphs 1 index get 1 add add
  444.         } repeat
  445.         1 add postglyphs exch 2 copy 1 sub get getinterval cvn
  446.         % At least some of Microsoft's TrueType fonts use incorrect
  447.         % (Adobe-incompatible) names for some glyphs.
  448.         % Correct for this here.
  449.         postremap 1 index .knownget { exch pop } if
  450.       } ifelse
  451.     } ifelse
  452.       } for ]
  453.     }
  454.     ifelse
  455.   } bind
  456.   16#00030000  {    % No map.
  457.     pop [ ]
  458.   } bind
  459. .dicttomark readonly def                % postformats
  460.  
  461. % Each procedure in this dictionary is called as follows:
  462. %    <file> <length> -proc- <string|array_of_strings>
  463. % Note that each table must have an even length, because of a strange
  464. % Adobe requirement that each sfnts entry have even length.
  465. /readtables mark
  466.     % Ordinary tables
  467.   (cmap) { .readtable }
  468.   (head) 1 index
  469.   (hhea) 1 index
  470.   (maxp) 1 index
  471.   (name) 1 index
  472.   (OS/2) 1 index
  473.   (post) 1 index
  474.   (vhea) 1 index
  475.     % Big tables
  476.   (glyf) { .readbigtable }
  477.   (loca) 1 index
  478.   (hmtx) 1 index
  479.   (vmtx) 1 index
  480.     % Tables only needed for embedding in PDF files
  481.   (cvt ) { .readtable }
  482.   (fpgm) 1 index
  483.   (prep) 1 index
  484. .dicttomark
  485. % Normally there would be a 'readonly' here, but the ttf2pf utility wants
  486. % to include the 'kern' table as well, so we leave the readtables dictionary
  487. % writable.
  488. def                % readtables
  489.  
  490. % Read a table as a single string.
  491. % <file> <length> .readtable <string>
  492. /.readtable {
  493.   dup dup 1 and add string
  494.         % Stack: f len str
  495.   dup 0 4 -1 roll getinterval
  496.         % Stack: f str str1
  497.     % Because of the absurd PostScript specification that gives an
  498.     % error for reading into an empty string, we have to check for
  499.     % this explicitly here.
  500.   3 -1 roll exch
  501.   dup () ne { readstring } if pop pop
  502. } bind def
  503.  
  504. % Read a big table (one that may exceed 64K).
  505. % <file> <length> .readbigtable <string[s]>
  506. /.readbigtable {
  507.   dup 65400 lt {
  508.     .readtable
  509.   } {
  510.     currentuserparams /VMReclaim get -2 vmreclaim
  511.     [ 4 2 roll {
  512.         % Stack: mark ... f left
  513.       dup maxstring le { exit } if
  514.       1 index maxstring string readstring pop 3 1 roll maxstring sub
  515.     } loop .readtable ]
  516.     exch vmreclaim
  517.   } ifelse
  518. } bind def
  519.  
  520. end readonly def                % .loadttfontdict
  521.  
  522. % <tab> .printtab -
  523. /.printtab {
  524.   dup 0 4 getinterval print ( ) print
  525.   dup 8 getu32 =only ( ) print
  526.   12 getu32 =
  527. } bind def
  528.  
  529. % <file> .loadttfonttables -
  530. % Pushes .loadttfontdict & scratch dict on d-stack.
  531. % Defines f, offsets, tables, tabdict, tabs.
  532. /.loadttfonttables {
  533.   .loadttfontdict begin
  534.   40 dict begin
  535.   /f exch def
  536.   /offsets f 12 string readstring pop def
  537.   /tables f offsets 4 getu16 16 mul string readstring pop def
  538.   /tabdict tables length 16 idiv dict def
  539.     % tabs = tables we want to keep, sorted by file position.
  540.   /tabs [ 0 16 tables length 1 sub {
  541.     tables exch 16 getinterval
  542.     DEBUG { dup .printtab } if
  543.     dup 0 4 getinterval readtables 1 index known {
  544.       tabdict exch 2 index put
  545.     } {
  546.       pop pop
  547.     } ifelse
  548.   } for ] {
  549.     exch 8 getu32 exch 8 getu32 lt
  550.   } .sort def
  551.     % In certain malformed TrueType fonts, tables overlap.
  552.     % Truncate tables if necessary.
  553.   0 1 tabs length 2 sub {
  554.     dup tabs exch get exch 1 add tabs exch get
  555.     1 index 8 getu32 2 index 12 getu32 add
  556.     1 index 8 getu32 gt {
  557.       (**** Warning: ) print 1 index 0 4 getinterval print
  558.       ( overlaps ) print dup 0 4 getinterval print
  559.       (, truncating.) = flush
  560.       dup 8 getu32 2 index 8 getu32 sub
  561.       2 index 12 3 -1 roll putu32
  562.     } if pop pop
  563.   } for
  564. } bind def
  565.  
  566. % - .readttdata -
  567. % Read data.  Updates offsets, tabs; stores data in tabdict.
  568. /.readttdata {
  569.   /fpos offsets length tables length add def
  570.   /sfpos offsets length tabs length 16 mul add def
  571.   offsets 4 tabs length putu16
  572.   tabs {
  573.     dup 0 4 getinterval /tname exch def
  574.     dup 8 getu32 /tpos exch def
  575.     dup 12 getu32 /tlen exch def
  576.     8 sfpos putu32
  577.     % Skip data between the end of the previous table and
  578.     % the beginning of this one, if any.
  579.     tpos fpos gt {
  580.       f tpos fpos sub () /SubFileDecode filter dup flushfile closefile
  581.       /fpos tpos def
  582.     } if
  583.     f tlen readtables tname get exec
  584.     tabdict tname 3 -1 roll put
  585.     /fpos fpos tlen add def
  586.     % Round up the table length to an even value.
  587.     /sfpos sfpos tlen dup 1 and add add def
  588.   } forall
  589. } bind def
  590.  
  591. % Find the string in a list of strings that includes a given index.
  592. % <strings> <index> .findseg <string> <index'>
  593. /.findseg {
  594.   exch {
  595.     dup length 2 index gt { exch exit } if
  596.     length sub
  597.   } forall
  598. } bind def
  599.  
  600. % - .makesfnts -
  601. % Defines checksum, getloca, head, locatable, numloca, post, sfnts, upem
  602. /.makesfnts {
  603.   .readttdata
  604.   /head tabdict /head get def
  605.   /locatable tabdict /loca get def
  606.   /post tabdict /post .knownget not { null } if def
  607.   /numloca
  608.     locatable dup type /stringtype eq
  609.      { length }
  610.      { 0 exch { length add } forall }
  611.     ifelse    % no def yet
  612.   locatable type /stringtype eq {
  613.     /.indexloca {} def
  614.   } {
  615.     /.indexloca /.findseg load def
  616.   } ifelse
  617.   head 50 getu16 0 ne {
  618.     /getloca {
  619.       2 bitshift locatable exch .indexloca getu32
  620.     } def
  621.     4 idiv 1 sub
  622.   } {
  623.     /getloca {
  624.       dup add locatable exch .indexloca getu16 dup add
  625.     } def
  626.     2 idiv 1 sub
  627.   } ifelse def        % numloca
  628.     % If necessary, re-partition the glyfs.
  629.   tabdict /glyf get dup type /stringtype ne {
  630.     .dividesfnts tabdict /glyf 3 -1 roll put
  631.   } {
  632.     pop
  633.   } ifelse
  634.   /sfnts [
  635.     offsets tabs { concatstrings } forall
  636.     tabs {
  637.       0 4 getinterval tabdict exch get
  638.       dup type /stringtype ne { aload pop } if
  639.     } forall
  640.   ] def
  641. } bind def
  642.  
  643. % <glyfs> .dividesfnts <glyfs'>
  644. /.dividesfnts {
  645.   /glyfs exch def
  646.   /len1 0 glyfs { length add } forall def
  647.         % Determine where to split the glyfs by scanning loca.
  648.         % The very last entry in loca may be bogus.
  649.         % Note that some loca entries may be odd, but we can only
  650.         % split at even positions.
  651.         %
  652.         % Construct splitarray, the array of final lengths of
  653.         % the sfnts entries covering the glyfs (i.e., all but
  654.         % the first and last sfnts entries).
  655.     /prevsplit 0 def
  656.     /prevboundary 0 def
  657.     /splitarray [
  658.       0 1 numloca 1 sub {
  659.     getloca dup prevsplit maxstring add gt {
  660.       prevboundary prevsplit sub exch
  661.       /prevsplit prevboundary def
  662.     } if
  663.     dup 1 and 0 eq { /prevboundary exch def } { pop } ifelse
  664.       } for
  665.       len1 prevsplit sub
  666.     ] def
  667.     currentuserparams /VMReclaim get -2 vmreclaim
  668.     [
  669.         % Re-split the sfnts glyfs strings according to splitarray.
  670.         % We do this by iterating over the final segments defined
  671.         % by splitarray, and constructing them from pieces of the
  672.         % current glyfs strings.  We recycle the current strings
  673.         % when possible, to avoid stressing the allocator.
  674.       /sfnt_idx 0 def
  675.       /strpos 0 def
  676.       /avail () def
  677.       splitarray {
  678.     /seglen exch def
  679.     /segpos 0 def
  680.     avail length seglen ge
  681.       { avail 0 seglen getinterval /avail () def } { seglen string }
  682.     ifelse
  683.     {
  684.       /str glyfs sfnt_idx get def
  685.       /strlen str length def
  686.       /strleft strlen strpos sub def
  687.       seglen segpos sub strleft lt { exit } if
  688.         % Copy the (rest of the) string into the new segment.
  689.         % We know strleft <= segleft.
  690.       dup segpos str strpos strleft getinterval putinterval
  691.       /segpos segpos strleft add def
  692.       /avail str def
  693.       /sfnt_idx sfnt_idx 1 add def
  694.       /strpos 0 def
  695.       segpos seglen eq { exit } if
  696.     } loop
  697.         % Fill up the segment with an initial piece of the next
  698.         % existing glyfs string.  We know strleft > segleft.
  699.     /segleft seglen segpos sub def
  700.     dup segpos str strpos segleft getinterval putinterval
  701.     /strpos strpos segleft add def
  702.       } forall
  703.     ]
  704.     exch vmreclaim
  705. } bind def
  706.  
  707. % - .getpost -
  708. % Uses post, defines glyphencoding
  709. /.getpost {
  710.   /glyphencoding post null eq {
  711.     DEBUG { (post missing) = flush } if [ ]
  712.   } {
  713.     postformats post 0 getu32 .knownget {
  714.       DEBUG {
  715.     (post: format ) print
  716.     post 0 getu16 =only (,) print post 2 getu16 = flush
  717.       } if
  718.       post exch exec
  719.     } {
  720.       DEBUG { (post: unknown format ) print post 0 getu32 = flush } if [ ]
  721.     } ifelse
  722.   } ifelse def
  723. } bind def
  724.  
  725. % - .ttkeys <key> <value> ...
  726. /.ttkeys {
  727.   count /ttkeycount exch def
  728.   /upem head 18 getu16 def
  729.   /FontMatrix matrix
  730.   /FontBBox [ 36 2 42 { head exch gets16 upem div } for ]
  731.   nextxuid
  732.   tabdict /name .knownget {
  733.         % Find the names from the 'name' table.
  734.     /names exch def
  735.     /FontName names 6 findname not { curxuid 16 8 string cvrs } if
  736.       /fontname 1 index def
  737.     /FontInfo mark
  738.       names 0 findname { /Notice exch } if
  739.       names 1 findname { /FamilyName exch } if
  740.       names 4 findname { /FullName exch } if
  741.       names 5 findname { /Version exch } if
  742.   } {
  743.         % No name table, fabricate a FontName.
  744.     /FontName curxuid 16 8 string cvrs
  745.       /fontname 1 index def
  746.     /FontInfo mark
  747.   } ifelse
  748.         % Stack: ... /FontInfo mark key1 value1 ...
  749.   post null ne {
  750.     /ItalicAngle post 4 gets32 65536.0 div
  751.     /isFixedPitch post 12 getu32 0 ne
  752.     /UnderlinePosition post 8 gets16 upem div
  753.     /UnderlineThickness post 10 gets16 upem div
  754.   } if
  755.   counttomark 0 ne { .dicttomark } { pop pop } ifelse
  756.   /XUID [orgXUID 42 curxuid]
  757.   DEBUG {
  758.     tabs { .printtab } forall
  759.     [ sfnts { length } forall ] ==
  760.     count ttkeycount sub array astore dup { == } forall aload pop
  761.   } if
  762.   /sfnts sfnts
  763. } bind def
  764.  
  765. % ---------------- Standard TrueType font loading ---------------- %
  766.  
  767. % - .pickcmap -
  768. % Defines cmapsub, cmaptab
  769. /.pickcmap {
  770.   tabdict /cmap get
  771.         % The Apple cmap format is no help in determining the encoding.
  772.         % Look for a Microsoft table.  If we can't find one,
  773.         % just use the first table, whatever it is.
  774.   dup 4 8 getinterval exch             % the default
  775.   0 1 2 index 2 getu16 1 sub {
  776.     8 mul 4 add 1 index exch 8 getinterval
  777.     DEBUG {
  778.       (cmap: platform ) print dup 0 getu16 =only
  779.       ( encoding ) print dup 2 getu16 = flush
  780.     } if
  781.     dup 0 getu16 3 eq { exch 3 -1 roll pop exit } if pop
  782.   } for
  783.         % Stack: subentry table
  784.   /cmapsub 2 index def
  785.   exch 4 getu32 1 index length 1 index sub getinterval
  786.   /cmaptab exch def
  787. } bind def
  788.  
  789. % <glyph> .nname <_name>
  790. /.nname {
  791.   =string cvs (_) exch concatstrings cvn
  792. } bind def
  793.  
  794. % - .charkeys /CharStrings <charstrings> /Encoding <encoding>
  795. % Resets glyphencoding
  796. /.charkeys {
  797.   DEBUG {
  798.     (glyphencoding: length=) print glyphencoding dup length = === flush
  799.   } if
  800.         % Hack: if there is no usable post table but the cmap uses
  801.         % the Microsoft Unicode encoding, use ISOLatin1Encoding.
  802.   glyphencoding length 0 eq cmapsub 0 4 getinterval <00030001> eq and {
  803.     /glyphencoding ISOLatin1Encoding dup length array copy def
  804.   } if
  805.         % If necessary, fabricate additional glyphencoding entries
  806.         % to cover all of loca, or truncate glyphencoding.
  807.   glyphencoding length numloca lt {
  808.     /glyphencoding numloca array
  809.       glyphencoding length dup 1 sub 0 1 3 2 roll {
  810.         dup glyphencoding exch get
  811.         3 index 3 1 roll put
  812.       } for
  813.       % /glyphencoding <newarray> <glyphencoding length>
  814.       1 numloca 1 sub {
  815.         1 index exch dup .nname put
  816.       } for
  817.     def
  818.   } {
  819.     /glyphencoding glyphencoding 0 numloca getinterval def
  820.   } ifelse
  821.         % Some badly designed Chinese fonts have a post table
  822.         % in which all glyphs other than 0 are named .null.
  823.         % Use CharStrings to keep track of the reverse map from
  824.         % names to glyphs, and don't let any name be used for
  825.         % more than one glyph.
  826.   /CharStrings glyphencoding dup length 1 add dict    % +1 for .notdef
  827.     0 1 3 index length 1 sub {
  828.         % Stack: glyphencoding dict index
  829.       2 index 1 index get 2 index 1 index known {
  830.         % The same name maps to more than one glyph.
  831.         % Change the name.
  832.     pop dup .nname 3 index 2 index 2 index put
  833.       } if
  834.       2 index exch 3 -1 roll put
  835.     } for exch pop
  836.         % If there is no .notdef entry, map it to glyph 0.
  837.   dup /.notdef known not { dup /.notdef 0 put } if
  838.   readonly
  839.   /Encoding
  840.     [ cmaptab cmaparray dup length 256 gt { 0 256 getinterval } if
  841.     { glyphencoding exch get } forall
  842.     counttomark 256 exch sub { /.notdef } repeat ]
  843.   DEBUG { (Encoding: ) print dup === flush } if
  844. } bind def
  845.  
  846. % -mark- <key> <value> ... .definettfont <font>
  847. /.definettfont {
  848.   /FontType 42
  849.   /PaintType 0
  850.   DEBUG {
  851.     (numloca=) print numloca =
  852.   } if
  853.   .dicttomark
  854.   end end dup /FontName get exch definefont
  855. } bind def
  856.  
  857. % <file> .loadttfont <type42font>
  858. /.loadttfont {
  859.   .loadttfonttables
  860.   .makesfnts
  861.   .getpost
  862.   .pickcmap
  863.   mark
  864.   .charkeys
  865.   .ttkeys
  866.   .definettfont
  867. } bind def
  868.  
  869. % ---------------- CIDFontType 2 font loading ---------------- %
  870.  
  871. % Create a string with N CIDs from the top of the stack.
  872. % <cid1> ... <cidN> <N> .makecidmap <string>
  873. /.makecidmap {
  874.   dup 2 mul string dup 3 -1 roll 1 sub 2 mul -2 0 {
  875.         % Stack: cids str str i2
  876.     2 copy 5 index -8 bitshift put
  877.     1 add 4 -1 roll 16#ff and put dup
  878.   } for pop
  879. } bind def
  880.  
  881. % -mark- <key> <value> ... .definettcidfont <font>
  882. /.definettcidfont {
  883.   /CIDFontName fontname
  884.   /CIDFontType 2
  885.   /CIDSystemInfo mark
  886.     /Registry (Adobe)
  887.     /Ordering (Japan1)        % adhoc
  888.     /Supplement 0
  889.   .dicttomark
  890.   /CharStrings mark /.notdef 0 .dicttomark
  891.         % The cmap isn't of any use even if it is present.
  892.         % Just construct an identity CIDMap covering all the glyphs.
  893.   mark 0 1 numloca 1 sub { } for
  894.   counttomark /cidcount exch def
  895.   cidcount maxstring le {
  896.         % Use a single string.
  897.     cidcount .makecidmap exch pop
  898.   } {
  899.         % We must use 2 strings.
  900.     maxstring .makecidmap counttomark 1 add 1 roll
  901.     counttomark .makecidmap exch pop exch 2 array astore
  902.   } ifelse
  903.   /CIDMap exch
  904.   /CIDCount cidcount
  905.   /GDBytes 2
  906.   .dicttomark
  907.   end end dup /CIDFontName get exch /CIDFont defineresource
  908. } bind def
  909.  
  910. % <file> .loadttcidfont <cidtype2font>
  911. /.loadttcidfont {
  912.   .loadttfonttables
  913.   .makesfnts
  914.     % CIDFontType2 fonts don't have a cmap: they are indexed by CID.
  915.   mark
  916.   .ttkeys
  917.   .definettcidfont
  918. } bind def
  919.  
  920. % ---------------- PDF TrueType font loading ---------------- %
  921.  
  922. % Strictly speaking, this code should be loaded only if we have a PDF
  923. % interpreter, but it's so closely tied to the rest of the code in this
  924. % file that we always include it.
  925.  
  926. % <plat+enc> .findcmap <subtable> true
  927. % <plat+enc> .findcmap false
  928. /.findcmap {
  929.   false exch tabdict /cmap get
  930.         % Some fonts have multiple cmaps with the same platform and
  931.         % encoding.  Use the first one we find.
  932.   0 1 2 index 2 getu16 1 sub {
  933.         % Stack: false plat+enc cmap index
  934.     8 mul 4 add 1 index exch 8 getinterval 
  935.     dup 0 4 getinterval 3 index eq {
  936.       4 getu32 1 index exch 1 index length 1 index sub getinterval
  937.       4 -1 roll not 4 2 roll exit
  938.     } if pop
  939.   } for
  940.         % Stack: false plat+enc cmap || subtable true plat+enc cmap
  941.   pop pop
  942. } bind def
  943.  
  944. % Build .symbol_list for .pdfcharkeys .
  945. % It is a dictionary containing all SymbolEncoding glyph names
  946. % and random names for filling gaps in the character code range.
  947. /.symbol_list 256 dict def
  948. {
  949.   =string 0 (x) 0 get put
  950.   /SymbolEncoding .findencoding
  951.   0 1 255 {
  952.     dup 2 index exch get
  953.     dup /.notdef eq {
  954.       pop dup
  955.       =string 1 3 getinterval cvs length 1 add
  956.       =string exch 0 exch getinterval cvn
  957.     } if
  958.     exch //.symbol_list 3 1 roll put
  959.   } for
  960.   pop
  961. } bind exec
  962.  
  963. % Create .GS_extended_SymbolEncoding as inverse of .symbol_list .
  964. {
  965.   /.GS_extended_SymbolEncoding 256 array
  966.   //.symbol_list {
  967.     exch 2 index 3 1 roll put  
  968.   } forall
  969.   .defineencoding
  970. } bind exec
  971.  
  972. /.addglyph    % <name> <glyph#> .addglyph <name> <glyph#> 
  973.               % <name> <glyph#> .addglyph -
  974. {
  975.   dup cmapencoding length lt {
  976.     cmapencoding exch get dup 0 eq {
  977.       pop pop
  978.     } if
  979.   } {
  980.     pop pop
  981.   } ifelse
  982. } bind def
  983.  
  984. % <subcmap> <chartoglyphmap> .pdfmapchars
  985. %   /CharStrings <charstrings>
  986. /.pdfmapchars {
  987.   exch cmaparray /cmapencoding exch def
  988.   /CharStrings mark 
  989.  
  990.   % Add glyphs of <chartoglyphmap>*<subcmap> :
  991.   3 2 roll {
  992.     dup type /arraytype eq {
  993.       exch /.name exch def
  994.       { .name exch //.addglyph exec
  995.       } forall
  996.       currentdict /.name undef
  997.     } {
  998.       //.addglyph exec
  999.     } ifelse
  1000.   } forall
  1001.  
  1002.         % stack: /CharStrings mark /name1 glyph#1 /name2 glyph#2 ... /namen glyph#n
  1003.         % Stack depth is restricted with AdobeGlyphList size.
  1004.  
  1005.   % Add glyphs of 'post' (with lower priority, see .dicttomark) :
  1006.   0 1 glyphencoding length 1 sub {
  1007.     dup glyphencoding exch get exch
  1008.     dup 0 eq {
  1009.       pop pop
  1010.     } if
  1011.   } for
  1012.  
  1013.   /.notdef 0
  1014.   .dicttomark
  1015. } bind def
  1016.  
  1017. % - .pdfcharkeys /CharStrings <charstrings> /Encoding <encoding>
  1018. /.pdfcharkeys {
  1019.     % The following algorithms are per the PDF Reference, Second Edition
  1020.     % (PDF 1.3 reference manual).
  1021.  
  1022.   is_symbolic {
  1023.     <00030001> .findcmap {
  1024.       %
  1025.       % Adobe PDF spec says that symbolic fonts should contain exactly one 
  1026.       % cmap subtable for Platform=1, Encoding=0.
  1027.       % Perhaps "Adobe Acrobat PDFWriter 4.0 for Windows" sometimes embeds
  1028.       % fonts with both subtables 3.1 and 1.0 (see comparefiles/159.pdf,
  1029.       % the font "Arial,Bold" with the character "registered"),
  1030.       % and both Acrobat Reader 4.0 and 5.0 choose 3.1.
  1031.       % Therefore we try 3.1 first.
  1032.       %
  1033.       (   **** Warning: Embedded symbolic TT fonts should not contain a cmap for Platform=3 Encoding=1.\n)
  1034.         pdfformaterror
  1035.       AdobeGlyphList .pdfmapchars 
  1036.       /Encoding /WinAnsiEncoding .findencoding
  1037.     } {
  1038.       %
  1039.       % Adobe PDF spec says that in this case PDF interpreter should
  1040.       % map character codes directly to glyphs using
  1041.       % the cmap <00010000>. But we use PS interpreter to emulate
  1042.       % a PDF interpreter. Therefore we need to construct
  1043.       % a type 42 font, which requires an Encoding and a Charstrings.
  1044.       % We construct them with symbol_list, which
  1045.       % includes all glyphs from SymbolEncoding and additional
  1046.       % random names for 1-to-1 mapping.
  1047.       %
  1048.       % A real TT font may use a different characters than
  1049.       % the Symbol charaster set. Perhaps our code
  1050.       % will give a correct printing, because glyph names are not
  1051.       % important for symbolic fonts in PDF.
  1052.       %
  1053.       <00010000> .findcmap {
  1054.         .symbol_list .pdfmapchars
  1055.         /Encoding /.GS_extended_SymbolEncoding .findencoding
  1056.       } {
  1057.         % This is illegal with PDF spec.
  1058.         (   **** Warning: Embedded symbolic TT fonts must contain a cmap for Platform=1 Encoding=0.\n)
  1059.           pdfformaterror
  1060.         % Try to map Unicode to SymbolEncoding
  1061.         <00030001> .findcmap {
  1062.           AdobeGlyphList .pdfmapchars
  1063.           /Encoding /SymbolEncoding .findencoding
  1064.         } {
  1065.           % Apply the default algorithm. Hopely it has 'post'.
  1066.           .charkeys
  1067.         } ifelse
  1068.       } ifelse
  1069.     } ifelse
  1070.   } {
  1071.     <00030001> .findcmap {
  1072.       AdobeGlyphList .pdfmapchars 
  1073.       /Encoding /WinAnsiEncoding .findencoding
  1074.         % WinAnsiEncoding is just a stub here. 
  1075.         % It will be replaced with one from font resource,
  1076.         % because PDF spec requires it.
  1077.     } {
  1078.       <00010000> .findcmap {
  1079.     .romanmacdict .pdfmapchars 
  1080.         /Encoding /MacRomanEncoding .findencoding
  1081.       } {
  1082.         % Apply the default algorithm for using the 'post'.
  1083.     .charkeys
  1084.       } ifelse
  1085.     } ifelse
  1086.   } ifelse
  1087. } bind def
  1088.  
  1089. % <file> <is_symbolic> .loadpdfttfont <type42font>
  1090. /.loadpdfttfont {
  1091.   /is_symbolic exch def
  1092.   .loadttfonttables
  1093.   .makesfnts
  1094.   .getpost
  1095.   .pickcmap
  1096.   mark
  1097.   .pdfcharkeys
  1098.   .ttkeys
  1099.   .definettfont
  1100. } bind def
  1101.